home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / TUT08NEW.ZIP / TUT8.CPP < prev    next >
C/C++ Source or Header  |  1995-01-14  |  19KB  |  478 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. //                                                                         //
  3. // TUTPROG8.CPP - VGA Trainer Program 8 (in Turbo C++ 3.0)                 //
  4. //                                                                         //
  5. // "The VGA Trainer Program" is written by Denthor of Asphyxia. However it //
  6. // was limited to only Pascal in its first run.  All I have done is taken  //
  7. // his original release, translated it to C++ and touched up a few things. //
  8. // I take absolutely no credit for the concepts presented in this code and //
  9. // am NOT the person to ask for help if you are having trouble.            //
  10. //                                                                         //
  11. // Program Notes : This program presents the basics of 3D.  Please note    //
  12. //                 that the compiled C++ version of this program runs      //
  13. //                 much faster than the Pascal version.  If you are        //
  14. //                 a 486DX/33 or higher, you may wish to turn turbo off.   //
  15. //                                                                         //
  16. //                 If you are compiling this program from within the       //
  17. //                 Turbo C++ environment, you must go under Options,       //
  18. //                 Debugger, and change the "Program Heap Size" to a value //
  19. //                 80 or greater.  If you are going to be fooling around   //
  20. //                 with the code a bit, I suggest raising this to about    //
  21. //                 100 just to be on the safe side.  You don't have to     //
  22. //                 worry about this if you are compiling command line.     //
  23. //                                                                         //
  24. //                 Just for reference, this is what I use:                 //
  25. //                                                                         //
  26. //                    tcc -mc -a -G -2 -O tut8.cpp                         //
  27. //                                                                         //
  28. //                 The way things are set up, there is no need to compile  //
  29. //                 or link tut8.cpp and gfx1.cpp seperately.               //
  30. //                                                                         //
  31. //                 The Compact memory model (-mc) seems to provide the     //
  32. //                 best results for this tutorial.  Remember, use this     //
  33. //                 memory model when you have little code (less than 64k)  //
  34. //                 and lots of data.                                       //
  35. //                                                                         //
  36. // Author        : Grant Smith (Denthor) - denthor@beastie.cs.und.ac.za    //
  37. // Translator    : Christopher G. Mann   - r3cgm@dax.cc.uakron.edu         //
  38. //                                                                         //
  39. // Last Modified : January 14, 1995                                        //
  40. //                                                                         //
  41. /////////////////////////////////////////////////////////////////////////////
  42.  
  43. //               //
  44. // INCLUDE FILES //
  45. //               //
  46.  
  47.   #include <alloc.h>
  48.                            // farcalloc()
  49.   #include <conio.h>
  50.                            // clrscr(), getch(), kbhit()
  51.   #include <dos.h>
  52.                            // FP_SEG, geninterrupt()
  53.   #include <iostream.h>
  54.                            // cout
  55.   #include <math.h>
  56.                            // sin(), cos()
  57.   #include <stdlib.h>
  58.                            // exit()
  59.   #include "gfx1.cpp"
  60.  
  61. //          //
  62. // TYPEDEFS //
  63. //          //
  64.  
  65.   typedef unsigned char byte;
  66.   typedef unsigned int  word;
  67.  
  68. //           //
  69. // CONSTANTS //
  70. //           //
  71.  
  72.   const MAXLINES = 12;     // the number of lines in our cube
  73.  
  74.   // The 3-D coordinates of our object ... stored as {X1,Y1,Z1},
  75.   // {X2,Y2,Z2} ... for the two ends of a line
  76.   const int Obj[MAXLINES][2][3] =
  77.     { {{-10,-10,-10}, { 10,-10,-10}}, //  0        .-----2----.
  78.       {{-10,-10,-10}, {-10, 10,-10}}, //  1       /|         /|
  79.       {{-10, 10,-10}, { 10, 10,-10}}, //  2      9 |        A |
  80.       {{ 10,-10,-10}, { 10, 10,-10}}, //  3     /  |       /  |
  81.       {{-10,-10, 10}, { 10,-10, 10}}, //  4    .------6---.   3
  82.       {{-10,-10, 10}, {-10, 10, 10}}, //  5    |   |      |   |
  83.       {{-10, 10, 10}, { 10, 10, 10}}, //  6    |   1      7   |
  84.       {{ 10,-10, 10}, { 10, 10, 10}}, //  7    |   |      |   |
  85.       {{-10,-10, 10}, {-10,-10,-10}}, //  8    5   '----0-|---'
  86.       {{-10, 10, 10}, {-10, 10,-10}}, //  9    |  /       |  /
  87.       {{ 10, 10, 10}, { 10, 10,-10}}, //  A    | 8        | B
  88.       {{ 10,-10, 10}, { 10,-10,-10}}  //  B    |/         |/
  89.     };                                //       `-----4----'
  90.  
  91. //                     //
  92. // FUNCTION PROTOTYPES //
  93. //                     //
  94.  
  95.   // MEMORY ALLOCATION FUNCTIONS
  96.   void SetUpVirtual ();
  97.   void ShutDown     ();
  98.  
  99.   // LOGO-FUNCTION
  100.   void DrawLogo     ();
  101.  
  102.   // 3D POINTS FUNCTIONS
  103.   void SetUpPoints  ();
  104.   void RotatePoints (int X, int Y, int Z);
  105.   void DrawPoints   ();
  106.   void ClearPoints  ();
  107.  
  108.   // MID-LEVEL FUNCTION
  109.   void MoveAround   ();
  110.  
  111. //            //
  112. // STRUCTURES //
  113. //            //
  114.  
  115.   // The data on every point we rotate
  116.   struct Point {
  117.     float    x;
  118.     float    y;
  119.     float    z;
  120.   };
  121.  
  122. //                              //
  123. // GLOBAL VARIABLE DECLARATIONS //
  124. //                              //
  125.  
  126.   byte far *Virscr=NULL;           // Pointer to our virtual screen
  127.   word Vaddr;                      // Segment of our virtual screen
  128.   float Lookup[360][2];            // Our sin and cos lookup table
  129.   int Xoff, Yoff, Zoff;            // Used for movement of the objects
  130.   Point Lines[MAXLINES][2];        // The base object rotated
  131.   Point Translated[MAXLINES][2];   // The rotated object
  132.  
  133.  
  134. ///////////////////////////////////////////////////////////////////////////////
  135. //                                                                           //
  136. //                                MAIN FUNCTION                              //
  137. //                                                                           //
  138. ///////////////////////////////////////////////////////////////////////////////
  139.  
  140. void main() {
  141.  
  142.   SetUpVirtual();
  143.   clrscr();
  144.   cout
  145.     << "Greetings and salutations! Hope you had a great Christmas and New\n"
  146.     << "year! ;-) ... Anyway, this tutorial is on 3-D, so this is what is\n"
  147.     << "going to happen ... a wireframe square will come towards you.\n"
  148.     << "When it gets close, you get control. ""A"" and ""Z"" control the Z\n"
  149.     << "movement, "","" and ""."" control the X movement, and ""S"" and ""X""\n"
  150.     << "control the Y movement. I have not included rotation control, but\n"
  151.     << "it should be easy enough to put in yourself ... if you have any\n"
  152.     << "hassles, leave me mail.\n\n";
  153.   cout
  154.     << "Read the main text file for ideas on improving this code ... and\n"
  155.     << "welcome to the world of 3-D!\n\n";
  156.   cout << "Hit any key to contine ...\n";
  157.   getch();
  158.  
  159.   SetMCGA();
  160.  
  161.   SetUpPoints();
  162.   MoveAround();
  163.  
  164.   ShutDown();
  165.   SetText();
  166.  
  167.   cout
  168.     << "All done. This concludes the eigth sample program in the ASPHYXIA\n"
  169.     << "Training series. You may reach DENTHOR under the names of GRANT\n"
  170.     << "SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS. I am also an avid\n"
  171.     << "Connectix BBS user, and occasionally read RSAProg.\n"
  172.     << "For discussion purposes, I am also the moderator of the Programming\n"
  173.     << "newsgroup on the For Your Eyes Only BBS.\n"
  174.     << "The numbers are available in the main text. You may also write to me at:\n"
  175.     << "             Grant Smith\n"
  176.     << "             P.O. Box 270\n"
  177.     << "             Kloof\n"
  178.     << "             3640\n"
  179.     << "I hope to hear from you soon!\n\n\n";
  180.   cout << "Hit any key to exit ...\n";
  181.   getch();
  182.  
  183. }
  184.  
  185.  
  186. /////////////////////////////////////////////////////////////////////////////
  187. //                                                                         //
  188. // SetUpVirtual() - This sets up the memory needed for the virtual screen. //
  189. //                                                                         //
  190. /////////////////////////////////////////////////////////////////////////////
  191.  
  192. void SetUpVirtual() {
  193.  
  194.   Virscr = (byte far *) farcalloc(64000,1);
  195.  
  196.   // always check to see if enough memory was allocated
  197.   if (Virscr == NULL) {
  198.     SetText();
  199.     cout << "Insufficient memory for virtual screens, exiting...";
  200.     exit(1);
  201.   }
  202.  
  203.   Vaddr = FP_SEG(Virscr);
  204.  
  205. }
  206.  
  207. /////////////////////////////////////////////////////////////////////////////
  208. //                                                                         //
  209. // ShutDown() - This frees the memory used by the virtual screen.          //
  210. //                                                                         //
  211. /////////////////////////////////////////////////////////////////////////////
  212.  
  213. void ShutDown() {
  214.   free(Virscr);
  215. }
  216.  
  217. /////////////////////////////////////////////////////////////////////////////
  218. //                                                                         //
  219. // DrawLogo() - This draws 'SNOWMAN' at the top of the screen in little    //
  220. //              balls.                                                     //
  221. //                                                                         //
  222. /////////////////////////////////////////////////////////////////////////////
  223.  
  224. void DrawLogo() {
  225.  
  226.   const byte ball[5][5] = { 0,1,1,1,0,
  227.                             1,4,3,2,1,
  228.                             1,3,3,2,1,
  229.                             1,2,2,2,1,
  230.                             0,1,1,1,0
  231.                           };
  232.  
  233.   const char *Logo[5] = { {"OOO OOO OOO O O O  O O  OOO OOO"},
  234.                           {"O   O O O O O O O O O O O O O O"},
  235.                           {"OOO O O O O O O O O O O OOO O O"},
  236.                           {"  O O O O O O O O O O O O O O O"},
  237.                           {"OOO O O OOO  O O  O O O O O O O"}
  238.                         };
  239.  
  240.   int loop1, loop2, loop3, loop4;
  241.  
  242.   Pal(13, 0,63, 0); // set the color for the cube lines
  243.   Pal( 1, 0, 0,40); // set the colors for the dots
  244.   Pal( 2, 0, 0,45);
  245.   Pal( 3, 0, 0,50);
  246.   Pal( 4, 0, 0,60);
  247.  
  248.   for (loop1=0; loop1<5; loop1++)        // for each line...
  249.     for (loop2=0; loop2<31; loop2++)       // is it active?
  250.       if (Logo[loop1][loop2] == 'O')
  251.       for (loop3=0; loop3<5; loop3++)        // y coordinate of the ball
  252.         for (loop4=0; loop4<5; loop4++)        // x coordinate of the ball
  253.           Putpixel ((loop2+1)*10+loop3, (loop1+1)*4+loop4,
  254.                     ball[loop3][loop4],Vaddr);
  255.  
  256. }
  257.  
  258. /////////////////////////////////////////////////////////////////////////////
  259. //                                                                         //
  260. // SetUpPoints() - This sets the basic offsets of the object, creates the  //
  261. //                 lookup table, and moves the object from a constant to a //
  262. //                 variable.                                               //
  263. //                                                                         //
  264. /////////////////////////////////////////////////////////////////////////////
  265.  
  266. void SetUpPoints() {
  267.  
  268.   int loop1;
  269.  
  270.   // set the starting offsets of the cube
  271.   Xoff =  160;
  272.   Yoff =  100;
  273.   Zoff = -256;
  274.  
  275.   // generate the sin() and cos() tables
  276.   for (loop1=0; loop1<361; loop1++) {
  277.     Lookup [loop1][0] = sin(rad(loop1));
  278.     Lookup [loop1][1] = cos(rad(loop1));
  279.   }
  280.  
  281.   // move the Obj constant array into the Lines array
  282.   for (loop1=0; loop1<MAXLINES; loop1++) {
  283.     Lines[loop1][0].x = Obj[loop1][0][0];
  284.     Lines[loop1][0].y = Obj[loop1][0][1];
  285.     Lines[loop1][0].z = Obj[loop1][0][2];
  286.     Lines[loop1][1].x = Obj[loop1][1][0];
  287.     Lines[loop1][1].y = Obj[loop1][1][1];
  288.     Lines[loop1][1].z = Obj[loop1][1][2];
  289.   }
  290.  
  291. }
  292.  
  293. /////////////////////////////////////////////////////////////////////////////
  294. //                                                                         //
  295. // RotatePoints() - This rotates object lines by X, Y, and Z.  Then it     //
  296. //                  places the result in Translated.                       //
  297. //                                                                         //
  298. /////////////////////////////////////////////////////////////////////////////
  299.  
  300. void RotatePoints (int X,int Y,int Z) {
  301.  
  302.   int loop1;
  303.   Point temp;
  304.  
  305.   // for each line...
  306.   for (loop1=0; loop1<MAXLINES; loop1++) {
  307.  
  308.     // start point of line
  309.  
  310.     temp.x = Lines[loop1][0].x;
  311.     temp.y = Lookup[X][1]*Lines[loop1][0].y - Lookup[X][0]*Lines[loop1][0].z;
  312.     temp.z = Lookup[X][0]*Lines[loop1][0].y + Lookup[X][1]*Lines[loop1][0].z;
  313.     Translated[loop1][0] = temp;
  314.  
  315.     if (Y > 0) {
  316.       temp.x = Lookup[Y][1]*Translated[loop1][0].x - Lookup[Y][0]*Translated[loop1][0].y;
  317.       temp.y = Lookup[Y][0]*Translated[loop1][0].x + Lookup[Y][1]*Translated[loop1][0].y;
  318.       temp.z = Translated[loop1][0].z;
  319.       Translated[loop1][0] =temp;
  320.     }
  321.  
  322.     if (Z > 0) {
  323.       temp.x = Lookup[Z][1]*Translated[loop1][0].x + Lookup[Z][0]*Translated[loop1][0].z;
  324.       temp.y = Translated[loop1][0].y;
  325.       temp.z = (-Lookup[Z][0])*Translated[loop1][0].x + Lookup[Z][1]*Translated[loop1][0].z;
  326.       Translated[loop1][0] = temp;
  327.     }
  328.  
  329.     // end point of line
  330.  
  331.     temp.x = Lines[loop1][1].x;
  332.     temp.y = cos(rad(X))*Lines[loop1][1].y - sin(rad(X))*Lines[loop1][1].z;
  333.     temp.z = sin(rad(X))*Lines[loop1][1].y + cos(rad(X))*Lines[loop1][1].z;
  334.     Translated[loop1][1] = temp;
  335.  
  336.     if (Y > 0) {
  337.       temp.x = cos(rad(X))*Translated[loop1][1].x - sin(rad(Y))*Translated[loop1][1].y;
  338.       temp.y = sin(rad(Y))*Translated[loop1][1].x + cos(rad(Y))*Translated[loop1][1].y;
  339.       temp.z = Translated[loop1][1].z;
  340.       Translated[loop1][1] = temp;
  341.     }
  342.  
  343.     if (Z > 0) {
  344.       temp.x = cos(rad(Z))*Translated[loop1][1].x + sin(rad(Z))*Translated[loop1][1].z;
  345.       temp.y = Translated[loop1][1].y;
  346.       temp.z = (-sin(rad(Z)))*Translated[loop1][1].x + cos(rad(Z))*Translated[loop1][1].z;
  347.       Translated[loop1][1] = temp;
  348.     }
  349.   }
  350. }
  351.  
  352. /////////////////////////////////////////////////////////////////////////////
  353. //                                                                         //
  354. // DrawPoints() - This draws the translated object to the virtual screen.  //
  355. //                                                                         //
  356. /////////////////////////////////////////////////////////////////////////////
  357.  
  358. void DrawPoints() {
  359.  
  360.   int loop1, nx, ny, nx2, ny2, temp;
  361.  
  362.   for (loop1=0; loop1<MAXLINES; loop1++) {
  363.     if ((Translated[loop1][0].z+Zoff<0) && (Translated[loop1][1].z+Zoff<0)) {
  364.  
  365.       // start point of line
  366.       temp = Translated[loop1][0].z + Zoff;
  367.       nx   = ((256*Translated[loop1][0].x) / temp) + Xoff;
  368.       ny   = ((256*Translated[loop1][0].y) / temp) + Yoff;
  369.  
  370.       // end point of line
  371.       temp = Translated[loop1][1].z + Zoff;
  372.       nx2  = ((256*Translated[loop1][1].x) / temp) + Xoff;
  373.       ny2  = ((256*Translated[loop1][1].y) / temp) + Yoff;
  374.  
  375.       // check to make sure the line is within bounds
  376.       if ((nx >-1) && (nx <320) && (ny >25) && (ny <200) &&
  377.           (nx2>-1) && (nx2<320) && (ny2>25) && (ny2<200))
  378.         Line(nx,ny,nx2,ny2,13,Vaddr);
  379.     }
  380.   }
  381. }
  382.  
  383. /////////////////////////////////////////////////////////////////////////////
  384. //                                                                         //
  385. // ClearPoints() - This clears the translated object from the virtual      //
  386. //                 screen ... believe it or not, this is faster than a     //
  387. //                 straight cls(0,vaddr);                                  //
  388. //                                                                         //
  389. /////////////////////////////////////////////////////////////////////////////
  390.  
  391. void ClearPoints() {
  392.  
  393.   int loop1, nx, ny, nx2, ny2, temp;
  394.  
  395.   for (loop1=0; loop1<MAXLINES; loop1++) {
  396.     if ((Translated[loop1][0].z+Zoff<0) && (Translated[loop1][1].z+Zoff<0)) {
  397.  
  398.       // start point of line
  399.       temp = Translated[loop1][0].z + Zoff;
  400.       nx   = ((256*Translated[loop1][0].x) / temp) + Xoff;
  401.       ny   = ((256*Translated[loop1][0].y) / temp) + Yoff;
  402.  
  403.       // end point of line
  404.       temp = Translated[loop1][1].z + Zoff;
  405.       nx2  = ((256*Translated[loop1][1].x) / temp) + Xoff;
  406.       ny2  = ((256*Translated[loop1][1].y) / temp) + Yoff;
  407.  
  408.       // check to make sure the line is within bounds
  409.       if ((nx >-1) && (nx <320) && (ny >25) && (ny <200) &&
  410.           (nx2>-1) && (nx2<320) && (ny2>25) && (ny2<200))
  411.         Line(nx,ny,nx2,ny2,0,Vaddr);
  412.     }
  413.   }
  414. }
  415.  
  416. /////////////////////////////////////////////////////////////////////////////
  417. //                                                                         //
  418. // MoveAround() - This is the main display function.  First it brings the  //
  419. //                object towards the viewer by increasing the Zoff, then   //
  420. //                it passes control to the user.                           //
  421. //                                                                         //
  422. /////////////////////////////////////////////////////////////////////////////
  423.  
  424. void MoveAround() {
  425.  
  426.   // For some reason, the values we defined Xoff, Yoff, and Zoff to be in
  427.   // the function SetUpPoints() won't hold until this point.  If you know
  428.   // the reason, please send it to r3cgm@dax.cc.uakron.edu
  429.   Xoff =  160;  // redefined
  430.   Yoff =  100;  // redefined
  431.   Zoff = -256;  // redefined
  432.  
  433.   int deg=0, loop1;
  434.   byte ch=1; // assign a dummy value to ch
  435.  
  436.   Cls(0,Vaddr);
  437.  
  438.   DrawLogo();
  439.  
  440.   for (loop1=(-256); loop1<(-39); loop1++) {
  441.     Zoff = loop1 * 2;
  442.     RotatePoints(deg,deg,deg);
  443.     DrawPoints();
  444.     Flip(Vaddr,VGA);
  445.     ClearPoints();
  446.     deg = (deg + 5) % 360;
  447.   }
  448.  
  449.   do {
  450.  
  451.     if (kbhit()) {
  452.       ch = getch();
  453.       switch (ch) {
  454.         // We are not going to use toupper() because if we did, we'd have
  455.         // to include the whole ctype.h file.  This might take a little more
  456.         // time, but the program will be smaller.  We already have 7 include
  457.         // files, and its getting a bit rediculous.
  458.         case 'A': case 'a': Zoff += 5; break;  // away
  459.         case 'Z': case 'z': Zoff -= 5; break;  // toward
  460.         case ',':           Xoff -= 5; break;  // left
  461.         case '.':           Xoff += 5; break;  // right
  462.         case 'S': case 's': Yoff -= 5; break;  // down
  463.         case 'X': case 'x': Yoff += 5; break;  // up
  464.       }
  465.     }
  466.     DrawPoints();
  467.     Flip(Vaddr,VGA);
  468.     ClearPoints();
  469.     RotatePoints(deg,deg,deg);
  470.     deg = (deg + 5) % 360;
  471.  
  472.     // if the key pressed above was 0 (i.e. a control character) then
  473.     // read the character code
  474.     if (ch == 0) ch = getch();
  475.  
  476.   } while (ch != 27); // if the escape code was 27 (escape key) then exit
  477. }
  478.